home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / PACKET / CBBS60SO.ZIP / MBIBM.C < prev    next >
Text File  |  1989-01-25  |  11KB  |  609 lines

  1. /*
  2.  *  MBIBM.C - 1/25/88 - System dependent functions.
  3.  *  For standard IBM PC, under MS-DOS 3.1 or later
  4.  *
  5.  * Uses calls thru int 14h to drivers that replace the regular
  6.  *  interrupt 14h drivers.
  7.  * Uses brkoff and brkon to disable/enable ctrl-brk by VE3GYQ
  8.  * - VE3GYQ and NK6K
  9.  *
  10.  */
  11.  
  12. #include "mb.h"
  13. #include <time.h>
  14. #include <dos.h>
  15.  
  16. /*
  17.  *  INT14 function codes.
  18.  */
  19.  
  20. #define SER_OUT   1     /* Character out serial port     */
  21. #define SER_IN    2     /* Character in from serial port */
  22. #define SER_STAT  3     /* Check status of serial port   */
  23. #define SER_INQ   4     /* Verify driver loaded          */
  24. #define SET_BUSY  8     /* Set port busy flag            */
  25. #define CLR_BUSY  9     /* Clear port busy flag          */
  26. #define PP_FLAG  10     /* Store port flag in bios       */
  27. #define PC_FLAG  11     /* Store command flag in bios    */
  28. #define GP_FLAG  12     /* Retreive port flag            */
  29. #define GC_FLAG  13     /* Retreive command flag         */
  30. #define GCMD     14     /* Get command from bios         */
  31. #define PCMD     15     /* Store command in bios         */
  32.  
  33. /*
  34.  *  INT21 Functions codes.
  35.  */
  36.  
  37. #define SETDATE  0x2b
  38. #define SETTIME  0x2d
  39.  
  40. #define SETDTA   0x1a
  41. #define GETDTA   0x2f
  42. #define GETFRE   0x36
  43. #define SRCFST   0x4e
  44. #define SRCNXT   0x4f
  45.  
  46. #define DV_PAUSE   0x1000 /* Relinquish control to other     */
  47. #define DV_BEGINC  0x101B /* Begin DV critical region        */
  48. #define DV_ENDC    0x101C /* End critical region             */
  49.  
  50. char l_date[7], l_time[5];
  51. long time();
  52. static union REGS inreg, outreg, ingive, outgive;
  53. char pt_flag = 0;
  54. char bios_call;
  55.  
  56. #define CMDPORT   15   /* Port for passing commands */
  57.  
  58. /*
  59.  *  Initialize the serial I/O system.
  60.  *  Ports are initialized by loading driver and then running mbmode.
  61.  */
  62.  
  63. ioinit()
  64. {
  65.   brkoff();   /* disable DOS ctrl-brk fn */
  66. }
  67.  
  68. dosinit()
  69. {
  70.  if (s_flag & s_dv)
  71.    {
  72.      ingive.x.ax = DV_PAUSE;
  73.      bios_call = 0x15;
  74.      printf ("Set for DESQview.\n");
  75.    }
  76.  }
  77.  
  78. iooff()
  79. {
  80.   brkon();    /* restore DOS ctrl-brk fn */
  81. }
  82.  
  83. /*
  84.  *  Switch out of the current window.
  85.  */
  86.  
  87. switchw()
  88. {
  89.   if (s_flag & s_dv)
  90.   int86(bios_call, &ingive, &outgive);
  91. }
  92. /*
  93.  *  Set the current I/O device.
  94.  */
  95.  
  96. ioport(pp)
  97. PORTS *pp;
  98. {
  99.   port = pp;
  100. }
  101.  
  102. breakport()
  103. {
  104.   inreg.x.dx = port->idn;
  105.   inreg.h.ah = 7;
  106.   int86( 0x14, &inreg, &outreg);
  107. }
  108.  
  109. isdcd()
  110. {
  111.    switch (port->dev)
  112.    {
  113.    case p_tnc:
  114.    case p_serial:
  115.       inreg.x.dx = port->idn;
  116.       inreg.h.ah = SER_STAT;
  117.       int86( 0x14, &inreg, &outreg );
  118.       return (0x80 & outreg.h.al);
  119.    default: return true;
  120.    }
  121.  }
  122.  
  123. /*
  124.  *  Suspend multitasking permitting only calling task to
  125.  *  continue execution.
  126.  */
  127.  
  128. begin_lock()
  129. {
  130.    inreg.x.ax = DV_BEGINC;
  131.    int86(0x15, &inreg, &outreg);
  132. }
  133.  
  134. /*
  135.  *  Resume multitasking.
  136.  */
  137.  
  138. end_lock()
  139. {
  140.    inreg.x.ax = DV_ENDC;
  141.    int86(0x15, &inreg, &outreg);
  142. }
  143.  
  144. /*
  145.  *  Mark all the ports in this window as busy.
  146.  */
  147.  
  148. setbusy()
  149. {
  150.   inreg.h.ah = SET_BUSY;
  151.   inreg.x.dx = CMDPORT;
  152.   inreg.h.al = window;
  153.   int86(0x14, &inreg, &outreg);
  154. }
  155.  
  156. /*
  157.  *  Mark all the ports in this window as idle.
  158.  */
  159.  
  160. clrbusy()
  161. {
  162.   inreg.h.ah = CLR_BUSY;
  163.   inreg.x.dx = CMDPORT;
  164.   inreg.h.al = window;
  165.   int86(0x14, &inreg, &outreg);
  166. }
  167.  
  168. /*
  169.  *  Store the port flag in the bios. Port flag bits set
  170.  *  indicate that the corresponding port is initialized
  171.  *  in a window.
  172.  */
  173.  
  174. putp_flag(c)
  175. byte c;
  176. {
  177.   inreg.h.ah = PP_FLAG;
  178.   inreg.x.dx = CMDPORT;
  179.   inreg.h.al = c;
  180.   int86(0x14, &inreg, &outreg);
  181.  
  182. }
  183. /*
  184.  *  Store the command flag in the bios. Command flag bits set
  185.  *  indicate that the corresponding port has a command waiting
  186.  *  for it to process. 
  187.  */
  188.  
  189. putc_flag(c)
  190. byte c;
  191. {
  192.   inreg.h.ah = PC_FLAG;
  193.   inreg.x.dx = CMDPORT;
  194.   inreg.h.bl = c;
  195.   int86(0x14, &inreg, &outreg);
  196. }
  197.  
  198. /*
  199.  *  Get the port flag from the bios. Port flag bits set
  200.  *  indicate that the corresponding port is initialized
  201.  *  in a window.
  202.  */
  203.  
  204. byte getp_flag()
  205. {
  206.   inreg.h.ah = GP_FLAG;
  207.   inreg.x.dx = CMDPORT;
  208.   int86(0x14, &inreg, &outreg);
  209.   return outreg.h.al;
  210.  
  211. }
  212. /*
  213.  *  Get the command flag from the bios. Command flag bits set
  214.  *  indicate that the corresponding port has a command waiting
  215.  *  for it to process. 
  216.  */
  217.  
  218. getc_flag()
  219. {
  220.   inreg.h.ah = GC_FLAG;
  221.   inreg.x.dx = CMDPORT;
  222.   int86(0x14, &inreg, &outreg);
  223.   c_flag = outreg.h.bl;
  224.   b_flag = outreg.h.bh;
  225. }
  226.  
  227. /*
  228.  *  Recover two characters from the bios storage area for use
  229.  *  as commands. Port->line will contain these on return.
  230.  */
  231.  
  232. getcomd()
  233. {
  234.   inreg.h.ah = GCMD;
  235.   inreg.x.dx = CMDPORT;
  236.   int86(0x14, &inreg, &outreg);
  237.   port->opt1 = outreg.h.bl;
  238.   port->opt2 = outreg.h.bh;
  239. }
  240.  
  241. /*
  242.  *  Pass a two character command to the bios storage area.
  243.  */
  244.  
  245. putcomd(c1, c2)
  246. char c1, c2;
  247. {
  248.   inreg.h.ah = PCMD;
  249.   inreg.x.dx = CMDPORT;
  250.   inreg.h.bl = c1;
  251.   inreg.h.bh = c2;
  252.   int86(0x14, &inreg, &outreg);
  253. }
  254.  
  255. /*
  256.  *  Return character from the current port.
  257.  */
  258.  
  259. char inchar()
  260. {
  261.   register char ch;
  262.  
  263.   if (port->dev is p_console)
  264.   { ch = bdos(7, 0, 0);if (ch is '\020') pt_flag = !pt_flag; }
  265.   else
  266.   {
  267.     inreg.h.ah = SER_IN;
  268.     inreg.x.dx = port->idn;
  269.     int86(0x14, &inreg, &outreg);
  270.     ch = (0x00ff & outreg.h.al);
  271.   }
  272.  
  273.   if (ch is del) ch = '\b';
  274.   if (port->dev is p_console) return ch;
  275.  
  276. /*
  277.  *  Input did not come from the console.
  278.  *  Echo the input to the console.
  279.  */
  280.  
  281.   if (!(port->ec)) return ch;
  282.  
  283.   if (ch isnt ctl_g)
  284.   {
  285.      bdos(2, ch, 0);
  286.      if (ch is '\r') bdos(2, '\n', 0);
  287.   }
  288.   return ch;
  289. }
  290.  
  291. /*
  292.  *  Return non-zero if a character waits at current input.
  293.  */
  294.  
  295. instat()
  296. {
  297.   register int st;
  298.  
  299.   if (port->dev is p_console) st = kbstat();
  300.   else
  301.   {
  302.     inreg.x.dx = port->idn;
  303.     inreg.h.ah = SER_STAT;
  304.     int86(0x14, &inreg, &outreg);
  305.     st = 0x01 & outreg.h.ah;
  306.   }
  307.  
  308.   if (!st) if (s_flag & s_dv)
  309.   if (port->flags & p_give)
  310.     int86(bios_call, &ingive, &outgive);
  311.  
  312.   return st;
  313. }
  314.  
  315. outi(ch)
  316. char ch;
  317. {
  318.   inreg.x.dx = port->idn;
  319.   inreg.h.ah = SER_STAT;
  320.  
  321. /*
  322.  *  Check if cts on and xmtr rgstr empty.
  323.  *  Else maybe give some time to other DV windows.
  324.  */
  325.  
  326.   int86(0x14, &inreg, &outreg);
  327.   while((0x2010 & outreg.x.ax) isnt 0x2010)
  328.   {
  329. /*
  330.     if (s_flag & s_dv)
  331.     if (port->flags & p_give) int86(bios_call, &ingive, &outgive);
  332. */
  333.     int86(0x14, &inreg, &outreg);
  334.   }
  335.  
  336. /*
  337.  *  Stuff the character out the port.
  338.  */
  339.  
  340.   inreg.h.ah = SER_OUT;
  341.   inreg.h.al = ch;
  342.   int86(0x14, &inreg, &outreg);
  343. }
  344.  
  345. /*
  346.  *  Put the character out the current port,
  347.  *  echo to console if the current port is not the console.
  348.  *  Note special handling of end-of-line character.
  349.  */
  350.  
  351. outchar(ch)
  352. char ch;
  353. {
  354.   if (ch is '\r') return;
  355.   if (ch is '\n') ch = '\r';
  356.  
  357. /*
  358.  *  Put it out to the console, if it is going there.
  359.  */
  360.  
  361.   if ((port->dev is p_console) or port->ec)
  362.   {
  363.     bdos(2, ch, 0);
  364.     if (ch is '\r') bdos(2,'\n',0);
  365.     if (pt_flag) { bdos(5,ch,0); if(ch is '\r') bdos(5,'\n',0); }
  366.   }
  367.  
  368. /*
  369.  *  If the port is the console, nothing more to do.
  370.  */
  371.  
  372.   if (port->dev is p_console) return;
  373.  
  374. /*
  375.  *  Stuff this byte out the port.
  376.  */
  377.  
  378.   outi(ch);
  379.   if (ch is '\r') if (port->flags & p_lf) outi('\n');
  380. }
  381.  
  382. outstr(cp)
  383. char *cp;
  384. {
  385.   while(*cp) outchar(*cp++);
  386. }
  387.  
  388. /*
  389.  *  Set the clock.
  390.  *  fld[1] has the date string.
  391.  *  fld[2] has the time string.
  392.  */
  393.  
  394. settime()
  395. {
  396.   inreg.h.ah = SETTIME;
  397.   inreg.h.ch = two(port->fld[2]);       /* Hour */
  398.   inreg.h.cl = two(port->fld[2]+2);     /* Minute */
  399.   inreg.x.dx = 0;                       /* Seconds and hundredths */
  400.   intdos(&inreg, &outreg);
  401.  
  402.   inreg.h.ah = SETDATE;
  403.   inreg.h.dl = two(port->fld[1]+4);      /* Day   */
  404.   inreg.h.dh = two(port->fld[1]+2);      /* Month */
  405.   inreg.x.cx = 1900 + two(port->fld[1]); /* Year  */
  406.   intdos(&inreg, &outreg);
  407. }
  408.  
  409. two(cp)
  410. char *cp;
  411. {
  412.   return (10 * (*cp - '0') + (*(cp + 1) - '0'));
  413. }
  414.  
  415. /*
  416.  *  Fill the globals "l_date", "l_time", and "dt" with
  417.  *  the current date and time by reading the system clock.
  418.  *  l_time is HHMM, l_date is YYMMDD.
  419.  *  dt has the format of a directory item date/time.
  420.  */
  421.  
  422. curtim()
  423. {
  424.   struct tm *ct;
  425.   long ltime;
  426.  
  427.   time(<ime);
  428.   ct = localtime(<ime);
  429.   sprintf(l_time, "%02d%02d", ct->tm_hour, ct->tm_min);
  430.   sprintf(l_date, "%02d%02d%02d", ct->tm_year, ct->tm_mon + 1, ct->tm_mday);
  431. /* month returned by localtime is 0-11 */
  432. }
  433.  
  434. /*
  435.  *  Check a timer.
  436.  */
  437.  
  438. chktmr(l)
  439. long l;
  440. {
  441.   long cur;
  442.  
  443.   time(&cur);
  444.   if (cur > l) return false;
  445.   return true;
  446. }
  447.  
  448. /*
  449.  *  Set a timer.
  450.  */
  451.  
  452. settmr(l, i)
  453. long *l;
  454. int i;
  455. {
  456.   long cur;
  457.  
  458.   time(&cur);
  459.   *l = cur + (long)i;
  460. }
  461.  
  462. /*
  463.  *  Wait a bit.
  464.  */
  465.  
  466. wait(sec)
  467. int sec;
  468. {
  469.   long l;
  470.  
  471.   settmr(&l, sec);
  472.   while (chktmr(l)) if (s_flag & s_dv)
  473.   int86(bios_call, &ingive, &outgive);
  474. }
  475.  
  476. /*
  477.  *  Directory access routines.
  478.  */
  479.  
  480. #define d_dir  0x10
  481.  
  482. /*
  483.  *  A directory item.
  484.  */
  485.  
  486. typedef struct
  487. {
  488.   char  res[21];
  489.   char  attr;
  490.   int   time;
  491.   int   date;
  492.   word  sizel;
  493.   word  sizeh;
  494.   char  name[13];
  495. } FCB;
  496.  
  497. static int olddta;
  498. static FCB fcb;
  499.  
  500. /*
  501.  *  Open directory, return first item.
  502.  */
  503.  
  504. diropen(cp, p, dirdef)
  505. char   *cp;
  506. DIRDEF *dirdef;
  507. DIRENT *p;
  508. {
  509.   long  csize;
  510.  
  511. /*
  512.  *  Save DOS current buffer.
  513.  */
  514.  
  515.   inreg.h.ah = GETDTA;
  516.   intdos(&inreg, &outreg);
  517.   olddta = outreg.x.bx;
  518.  
  519. /*
  520.  *  Point DOS at local buffer.
  521.  */
  522.  
  523.   inreg.h.ah = SETDTA;
  524.   inreg.x.dx = (int)&fcb;
  525.   intdos(&inreg, &outreg);
  526.  
  527. /*
  528.  *  Get disk free space.
  529.  */
  530.  
  531.   inreg.h.ah = GETFRE;
  532.   if (*(cp + 1) is ':') inreg.h.dl = toupper(*cp) - 'A' + 1; else inreg.h.dl = 0;
  533.  
  534.   intdos(&inreg, &outreg);
  535.  
  536. /*
  537.  *  Compute device size.
  538.  *  ax = sectors / cluster
  539.  *  bx = available clusters
  540.  *  cx = bytes / sector
  541.  *  dx = total cluster / drive
  542.  */
  543.  
  544.   csize = (long)outreg.x.ax * (long)outreg.x.cx;
  545.   dirdef->size = (int)((csize * (long)outreg.x.dx + 1023l) / 1024l);
  546.   dirdef->free = (int)((csize * (long)outreg.x.bx + 1023l) / 1024l);
  547.  
  548. /*
  549.  *  Get the first directory entry.
  550.  */
  551.  
  552.   if (port->flds is 1) strcat(cp, "*.*");
  553.   if (port->mode & (local | sysop)) inreg.x.cx = d_dir; else inreg.x.cx = 0;
  554.   inreg.x.dx = (int)cp;
  555.  
  556.   inreg.h.ah = SRCFST;
  557.   while (true)
  558.   {
  559.     if (intdos(&inreg, &outreg))
  560.     {
  561.       p->size    = -1;
  562.       inreg.h.ah = SETDTA;
  563.       inreg.x.dx = olddta;
  564.       intdos(&inreg, &outreg);
  565.       return false;
  566.     }
  567.     if (dodir(p)) return true;
  568.     inreg.h.ah = SRCNXT;
  569.   }
  570. }
  571.  
  572. /*
  573.  *  Return second and succeding directory entries.
  574.  */
  575.  
  576. dirnext(p, dirdef)
  577. DIRENT *p;
  578. DIRDEF *dirdef;
  579. {
  580.   inreg.h.ah = SRCNXT;
  581.   while(true)
  582.   {
  583.     if (intdos(&inreg, &outreg))
  584.     {
  585.       p->size    = -1;
  586.       inreg.h.ah = SETDTA;
  587.       inreg.x.dx = olddta;
  588.       intdos(&inreg, &outreg);
  589.       return;
  590.     }
  591.     if (dodir(p)) return;
  592.   }
  593. }
  594.  
  595. dodir(p)
  596. DIRENT *p;
  597. {
  598.   strcpy(p->name, fcb.name);
  599.  
  600.   if (fcb.attr & d_dir)
  601.   {
  602.     if (match(p->name, "."))  return false;
  603.     if (match(p->name, "..")) return false;
  604.     strcat(p->name, "\\");
  605.   }
  606.   p->size = (int)((65536l * (long)fcb.sizeh + (long)fcb.sizel + 1023l) / 1024l);
  607.   return true;
  608. }
  609.